[WIP] Pressure Based Solver - #2812
Conversation
There was a problem hiding this comment.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
Implements the full class structure required for the pressure-based solver in a minimal form. The code compiles and runs but does not yet contain any numerical/physical implementation. Future work will focus on implementing solver logic. Note: In the previous attempts (see related work) there is noticeable code duplication between CIncEuler and CPBIncEuler. The final architecture may be revised depending on how the implementation of CPBIncEuler evolves.
Centered residual is not yet implemented as the old code did not have a working version. Upwind residual is functional but requires cleanup and move to more appropiate file.
Variables are a work in progress and still include some commented out code related to energy and pressure
The current viscous residual of the poisson equation uses an isotropic diffusion coefficient, this should not be the case and should thus be replaced
|
I will have to review the code myself first, it is not ready for review as of yet. |
pcarruscag
left a comment
There was a problem hiding this comment.
There are some errors in the implementation, which I made myself when I first implemented SIMPLE, and they are easy to make because certain simplifications look equivalent but are not.
For professional reasons I should discuss this only in terms of my prior work.
Here is an implementation that I think is mostly correct: https://github.com/pcarruscag/Flow-Solver-Experiments/blob/main/lib/flow/src/flow_simple.cpp
It's written in a funny way because it was my first exercise into porting something to GPUs, but follow the operations, and their order, not the code itself.
The main error here is that you do not carry nor correct the face velocities (or face mass flows), nor use them to discretize momentum and scalars.
You correct the nodal velocities (equivalent to cell centers) but that is not the same thing.
I was not nice enough to my future self to document why in my old code, but I'm somewhat confident an AI can explain the nuance.
|
@pcarruscag Thanks for the very usefull explanation of the issue. I think I now more or less fixed it. I also rewrote CPBFluidIteration.cpp, and I think the flow of the algorithm (and the changes I now made to it) should be clear in there. |
| /*--- Rhie Chow interpolation ---*/ | ||
| Coord_i = geometry->nodes->GetCoord(iPoint); | ||
| Coord_j = geometry->nodes->GetCoord(jPoint); | ||
| dist_ij_2 = 0.0; | ||
| for (iDim = 0; iDim < nDim; iDim++) { | ||
| Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; | ||
| dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; | ||
| } | ||
| /*--- 1. Interpolate the pressure gradient based on node values ---*/ | ||
| for (iDim = 0; iDim < nDim; iDim++) { | ||
| Grad_Avg = 0.5*(nodes->GetGradient_Primitive(iPoint,0,iDim) + nodes->GetGradient_Primitive(jPoint,0,iDim)); | ||
| GradP_in[iDim] = Grad_Avg; | ||
| } | ||
|
|
||
| /*--- 2. Compute pressure gradient at the face ---*/ | ||
| /*--- Eq 15.62 F Moukalled, L Mangani M. Darwish OpenFOAM and uFVM book. ---*/ | ||
| GradP_proj = 0.0; | ||
| for (iDim = 0; iDim < nDim; iDim++) { | ||
| GradP_proj += GradP_in[iDim]*Edge_Vector[iDim]; | ||
| } | ||
| if (dist_ij_2 != 0.0) { | ||
| for (iDim = 0; iDim < nDim; iDim++) { | ||
| GradP_f[iDim] = GradP_in[iDim] - (GradP_proj - (nodes->GetPressure(jPoint) - nodes->GetPressure(iPoint)))*Edge_Vector[iDim]/ dist_ij_2; | ||
| } | ||
| } |
There was a problem hiding this comment.
Can you extract a common helper from the numerics classes? this is similar to the corrected gradient calculation.
6c6d3e7 to
ce55da3
Compare
Proposed Changes
The current work (part of GSoC) provides a working version of a pressure-based algorithm for the incompressible flow solver as an alternative to the existing Density-based solver. Below, the reader may find the algorithm which has been implemented, as well as the current progress of the code and challenges. All the way at the bottom one can find performance comparisons between the DB and PB solvers for some test cases.
Algorithm
A lot of versions of pressure-based algorithms exist, and many different versions can be implemented. Here, we opt for versions of the original SIMPLE/PISO algorithm, it is briefly defined here for clarity.
First, the momentum equations are solved, starting from the previous time step's velocity$\vec{u}^{(0)}$, pressure$p^{(0)}$ , and face velocity $\vec{u}_f^{(0)}$ . The resulting momentum is the predicted momentum, here its discretized form is shown, as its coefficients are used in the subsequent equations
The subsequent momentum is not necessarily incompressible, the pressure correction equation can be derived by rewriting it as follows, using a term often called H by A
Note how a simplification is used here where the HbyA term is neglected. Subtracting these two equations yields the first pressure correction equation for$p'$ as
Make note that for the divergence here, we require the face mass fluxes, which are computed using Rhie-Chow interpolation to avoid odd-even decoupling. After the equation is solved, using the pressure correction$p'$ , the pressure and momentum are corrected according to
So far, this is equal to a pseudo-transient version of the SIMPLE algorithm. This algorithm however suffers from a very tight stability condition on the time-step size. Therefore, multiple pressure corrections can be applied, which for two corrections is originally called the PISO algorithm.
The second pressure correction does not neglect the HbyA term, which then results in the equation
And the new correction equations are defined as
Note that HbyA here uses the previous velocity correction and is thus the same quantity as the one used in the second pressure correction equation. Later pressure correction equations follow analogously.
Progress:
Issues
Performance:
The Poisson solver can sometimes struggle a lot due to high Reynolds numbers and fine meshes, and thus require a ridiculous number of iterations to converge reasonably. Possible fixes include adding multigrid support or a DIC preconditioner (far less efficient). Multigrid support is tricky as SU2 currently only considers multigrid for the main (flow) solver and not for auxiliary solvers.
Convergence issues with RANS (SA and SST) on fine meshes with high Reynolds numbers. Tests have shown that cases such as flow over a flat plate converges fine. However, external aerodynamic cases such as the naca0012 RANS test case do not converge well at all. The convergence does slightly improve when we switch out the mesh for a more uniform unstructured mesh without large aspect ratio cells in the wake of the airfoil, although this only slightly helps. The flat plate turbulence test case also uses large aspect ratio cells so this is not the sole issue. The RANS solver also often requires many iterations of the Poisson solver to converge reasonably, this is however not the reason for the lack of convergence.
Periodic boundary conditions have not been implemented/tested at all as of yet.
Any code related to adjoints has not been considered at all either.
Code:
TODO list
Related Work
This work is based on earlier attempts by Nitish Anand (2024) and Akshay Koodly (2021), see feature branches feature_PBFlow_V8 and feature_Pressure_based respectively. Also see PR #2210
PR Checklist
pre-commit run --allto format old commits.Result showcase
Inviscid Hydrofoil
Convergence history of the inviscid flow around a hydrofoil at a 5 degree aoa.
The pressure coefficient along the surface of the hydrofoil at a 5 degree aoa and the corresponding lift coefficients, X-FOIL predicts C_L=0.6.
Lid Driven Cavity
Convergence history of the lid driven cavity problem, note that CFL=60 is the highest stable CFL for the PB solver, whereas the DB solver does not have this CFL related stability issue.
Flatplate RANS
The skin friction coefficient for turbulent flow over a (rough) flat plate with SA.